#include <iostream>
#include <functional>
#include <vector>
#include <memory>
#include "err.hpp"
#include "tcpserver.hpp"
#include "protocol.hpp"
using namespace std;
using namespace TCP_sv;

static void Usage(string proc)
{
    cerr << "Usage:\n\t" << proc << " port "
         << "\n\n";
}

string resp(const string &s)
{
    return s;
}

bool cal(const Request &req, Response &resp)
{
    // req已经有结构化完成的数据啦，你可以直接使用
    resp._exitcode = NONE;
    resp._result = NONE;

    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
    {
        if (req._y == 0)
            resp._exitcode = DIV_ZERO;
        else
            resp._result = req._x / req._y;
    }
    break;
    case '%':
    {
        if (req._y == 0)
            resp._exitcode = MOD_ZERO;
        else
            resp._result = req._x % req._y;
    }
    break;
    default:
        resp._exitcode = OP_ERR;
        break;
    }

    return true;
}

void calculate(Connection *conn)
{
    string onepackage;
    // 从完整报文中取出有效载荷
    while (handleOnePackage(conn->_inbuffer, &onepackage))
    // 如果是读到一个完整的报文，就进入while循环体内对报文进行处理，形成响应返回给client端
    {
        //去报头
        string req_str;
        if(!deLength(onepackage,&req_str))
        {
            logMessage(FATAL,"delength err");
            return;
        }
        cout << "有效载荷: " << req_str << endl;
        // 反序列化：用有效载荷去构造req对象
        Request req;
        if (!req.Deserialize(req_str))
        {
            logMessage(FATAL, "Deserialize err");
            return;
        }
        // 用req对象的成员去构造resp对象--处理函数，然后构造响应
        Response resp;
        cal(req, resp);
        string respstr;
        // 用resp对象去序列化出一个报文
        if (!resp.Serialize(&respstr))
        {
            logMessage(FATAL, "resp serialize err");
            return;
        }
        // 将报文加上报头，然后填充到输出缓冲区中
        conn->_outbuffer += enLength(respstr);
        cout << "-----result: " << conn->_outbuffer << endl;
    }
    //
    if (conn->_writer)
        conn->_writer(conn);

    if (!conn->_outbuffer.empty()) // 如果没有发送完
        conn->_tcps->EnableReadWrite(conn, true, true);//如果这次数据没发完，下次epoll检查就绪事件时当前的sock的写事件还是就绪的，那么下次epoll就自动调用写函数继续写
    else
        conn->_tcps->EnableReadWrite(conn, true, false);//通过回调指针调用tcp对象的函数。这次写完了，将写事件关闭
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    unique_ptr<Tcpserver> selsv(new Tcpserver(calculate, port));
    selsv->inittcpserver();
    selsv->Distribute();

    return 0;
}